package atom.core0.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * <p>
 * Title:压缩工具类。支持压缩单个文件，只支持标准GZIP格式
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2004
 * </p>
 * 
 * @author 赵明才
 * @version 1.0
 */
// GZIPInputStream对象则进一步将流的数据加工进行细化，用于读取GZIP格式的压缩数据，
// 同理，GZIPOutputStream对象用于创建GZIP格式的压缩数据文件。

public class GZip {

	public static void main(String[] args) {
		try {
			// gzfile("d:\\药店进价一览表.xls","d:\\药店进价一览表.xls.zip");
			String s = "d:\\药店进价一览表.xls";
			byte[] b1, b2;

			b1 = gzMemory(s.getBytes(), 0, s.getBytes().length);
			b2 = ungzMemory(b1, b1.length);
			System.out.println("b1=" + b1);
			System.out.println("b2=" + new String(b2));
		} catch (Exception e) {

		}
	}

	public static byte[] gzMemory(byte[] in, int inStart, int inLen) throws IOException {
		byte[] data = null;
		// 建立字节数组输出流
		ByteArrayOutputStream o = new ByteArrayOutputStream();
		// 建立gzip压缩输出流
		GZIPOutputStream gzout = new GZIPOutputStream(o);
		gzout.write(in, inStart, inLen);
		gzout.close();
		o.close();
		// 必须在关闭流后取数据
		data = o.toByteArray();
		return data;

	}

	public static byte[] ungzMemory(byte[] in, int inLen) throws IOException {
		byte[] data = null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		// 建立字节数组输入流
		ByteArrayInputStream i = new ByteArrayInputStream(in, 0, inLen);
		// 建立gzip压缩输出流
		GZIPInputStream gzin = new GZIPInputStream(i);
		// gzin.read(in, 0, inLen);
		// gzin.read(data);
		byte[] buffer = new byte[1024];
		int n;
		while ((n = gzin.read(buffer)) >= 0) {
			out.write(buffer, 0, n);
		}
		i.close();
		gzin.close();
		out.close();

		data = out.toByteArray();
		return data;

	}

	public static void gzfile(String inFile, String outFile) throws IOException {
		// 打开需压缩文件作为文件输入流
		FileInputStream fin = new FileInputStream(inFile);
		// 建立压缩文件输出流
		FileOutputStream fout = new FileOutputStream(outFile);
		// 建立gzip压缩输出流
		GZIPOutputStream gzout = new GZIPOutputStream(fout);
		byte[] buf = new byte[1024];// 设定读入缓冲区尺寸
		int num;

		while ((num = fin.read(buf)) != -1) {
			gzout.write(buf, 0, num);
		}
		gzout.close();// !!!关闭流,必须关闭所有输入输出流.保证输入输出完整和释放系统资源.
		fout.close();
		fin.close();

	}

	public static void ungzfile(String inFile, String outFile) throws IOException {
		// 建立gzip压缩文件输入流
		FileInputStream fin = new FileInputStream(inFile);
		// 建立gzip解压工作流
		GZIPInputStream gzin = new GZIPInputStream(fin);
		// 建立解压文件输出流
		FileOutputStream fout = new FileOutputStream(outFile);
		byte[] buf = new byte[1024];
		int num;

		while ((num = gzin.read(buf, 0, buf.length)) != -1) {
			fout.write(buf, 0, num);
		}
		gzin.close();
		fout.close();
		fin.close();

	}

	// 将Data(Serializable)类型数据对象序列化对象压缩,返回字节数组,压缩后的对象数组可写入文件保存或用于网络传输
	public static byte[] writeCompressObject(Serializable object_) throws IOException {
		byte[] data_ = null;
		// 建立字节数组输出流
		ByteArrayOutputStream o = new ByteArrayOutputStream();
		// 建立gzip压缩输出流
		GZIPOutputStream gzout = new GZIPOutputStream(o);
		// 建立对象序列化输出流
		ObjectOutputStream out = new ObjectOutputStream(gzout);
		out.writeObject(object_);
		out.flush();
		out.close();
		gzout.close();
		// 返回压缩字节流
		data_ = o.toByteArray();
		o.close();
		return (data_);
	}

	// 将压缩字节数组还原为Data类型数据对象
	public static Serializable readCompressObject(byte[] data_) throws Exception {
		Serializable object_ = null;
		// 建立字节数组输入流
		ByteArrayInputStream i = new ByteArrayInputStream(data_);
		// 建立gzip解压输入流
		GZIPInputStream gzin = new GZIPInputStream(i);
		// 建立对象序列化输入流
		ObjectInputStream in = new ObjectInputStream(gzin);
		// 按制定类型还原对象
		object_ = (Serializable) in.readObject();
		i.close();
		gzin.close();
		in.close();
		return (object_);
	}

}
